package cn.dakaqi.utils.img;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

/**
 * 图片处理
 *
 * @author root
 */
public class ImageUtil
{

    static Logger log = LoggerFactory.getLogger(ImageUtil.class);

    /**
     * 复制指定图片文件，并按指定最大宽度裁剪为合适尺寸图片，返回图片名称
     *
     * @param imageSavePath 原始图片文件保存路径（物理路径）
     * @param fileName      原始图片名称（带文件后缀）
     * @param maxWidth      裁剪出的图片最大宽度
     * @return
     * @throws Exception
     */
    public static String copyAndCutImage(String imageSavePath, String fileName, int maxWidth) throws Exception
    {

        //0.检查原始图片宽度是否超出限制宽度，如果没有超出，返回原始图片名称
        String imgsrc = imageSavePath + fileName;

        log.info("---------image path:" + imgsrc);

        if (!ImageUtil.outOffMaxWidth(imgsrc, maxWidth)) return fileName;

        //1.生成新文件名称
        String newImageName = getFileNameByTime(fileName);

        //2.获得原文件保存物理路径， 新文件物理路径

        String imgdist = imageSavePath + newImageName;

        //3.裁剪,生成新文件
        compressImg(imgsrc, imgdist, maxWidth);


        return newImageName;
    }

    public static String getFileNameByTime(String fileName)
    {

        Date date = new Date();

        //获得系统当前时间
        String time = String.valueOf(date.getTime());

        //获得文件名后缀
        int index = fileName.lastIndexOf(".");

        String ext = fileName.substring(index, fileName.length());

        //组合成新文件名
        String newFileName = time + ext;

        System.out.println("-----------new file name:" + newFileName);


        return newFileName;
    }


    /**
     * 按指定宽度裁剪图片，并删除原图
     *
     * @param imageSavePath
     * @param fileName
     * @param maxWidth
     * @return
     * @throws Exception
     */
    public static String cutImageAndDelSrc(String imageSavePath, String fileName, int maxWidth) throws Exception
    {

        //0.检查原始图片宽度是否超出限制宽度，如果没有超出，返回原始图片名称
        String imgsrc = imageSavePath + fileName;

        log.info("---------image path:" + imgsrc);

        if (!ImageUtil.outOffMaxWidth(imgsrc, maxWidth)) return fileName;

        //1.生成新文件名称
        String newImageName = getFileNameByTime(fileName);

        //2.获得原文件保存物理路径， 新文件物理路径

        String imgdist = imageSavePath + newImageName;

        //3.裁剪,生成新文件
        compressImg(imgsrc, imgdist, maxWidth);

        //4.删除原图
        deleteImage(imgsrc);

        return newImageName;
    }

    /**
     * 删除图片
     *
     * @param imgsrc
     * @throws Exception
     */
    private static void deleteImage(String imgsrc) throws Exception
    {

        File srcFile = new File(imgsrc);

        if (srcFile != null)
        {

            srcFile.delete();
        }
    }


    /**
     * 检查图片宽度是否超出限制宽度
     *
     * @param imgsrc
     * @param maxWidth
     * @return
     */
    private static boolean outOffMaxWidth(String imgsrc, int maxWidth)
    {

        //获得原图片宽度高度
        int imgsize[] = getImgSize(imgsrc);

        int widthsrc = imgsize[0];

        //检查原始宽度是否超出最大宽度,如果没有超出最大宽度，什么都不做
        if (widthsrc <= maxWidth) return false;


        return true;
    }


    /**
     * 从图片访问路径中截取图片访问路径的根部分（剔除图片名称的部分）
     *
     * @param imageUrl
     * @return
     * @throws Exception
     */
    public static String getImageUrlRootFromImageUrl(String imageUrl) throws Exception
    {

        if (imageUrl == null || imageUrl.trim().equals("")) throw new Exception("image Url is null");

        int index = imageUrl.lastIndexOf("/");

        if (index < 0) throw new Exception("imageurl error!" + imageUrl);

        String rootUrl = imageUrl.substring(0, index + 1);

        return rootUrl;
    }


    /**
     * 从图片访问路径中截取图片文件名称（带文件扩展名）
     *
     * @param imageUrl
     * @return
     * @throws Exception
     */
    public static String getImageFileNameFromImageUrl(String imageUrl) throws Exception
    {

        if (imageUrl == null || imageUrl.trim().equals("")) throw new Exception("image Url is null");

        int index = imageUrl.lastIndexOf("/");

        if (index < 0) throw new Exception("imageurl error!" + imageUrl);

        String fileName = imageUrl.substring(index + 1, imageUrl.length());

        return fileName;
    }


    /**
     * 图片等比例压缩
     *
     * @param imgsrc   原图物理路径
     * @param imgdist  新图片保存物理路径
     * @param maxWidth 新图片最大宽度
     */
    public static void compressImg(String imgsrc, String imgdist, int maxWidth)
    {

        //获得原图片宽度高度
        int imgsize[] = getImgSize(imgsrc);

        int widthsrc = imgsize[0];

        int heightsrc = imgsize[1];

        //计算压缩比率
        float rate = (float) maxWidth / (float) widthsrc;

        log.info("--------compressImg-1-------maxWidth:" + maxWidth);

        log.info("--------compressImg-1-------rate:" + rate);


        log.info("--------compressImg-1-------widthsrc:" + widthsrc);

        log.info("--------compressImg-1-------heightsrc:" + heightsrc);

        //计算获得新图片宽度，高度
        int widthdist = (int) ((int) widthsrc * rate);

        int heightdist = (int) ((int) heightsrc * rate);

        log.info("--------compressImg-2-------widthdist:" + widthdist);

        log.info("--------compressImg-2-------heightdist:" + heightdist);

        //压缩图片
        reduceImg(imgsrc, imgdist, widthdist, heightdist);

    }


    /**
     * 压缩图片
     *
     * @param imgsrc     原图片物理路径
     * @param imgdist    新图片保存物理路径
     * @param widthdist  新图片宽度
     * @param heightdist 新图片高度
     */
    public static void reduceImg(String imgsrc, String imgdist, int widthdist,
                                 int heightdist)
    {
        try
        {

            File srcfile = new File(imgsrc);
            if (!srcfile.exists())
            {
                return;
            }
            Image src = ImageIO.read(srcfile);

            BufferedImage tag = new BufferedImage((int) widthdist,
                    (int) heightdist, BufferedImage.TYPE_INT_RGB);

            tag.getGraphics().drawImage(
                    src.getScaledInstance(widthdist, heightdist,
                            Image.SCALE_SMOOTH), 0, 0, null);

            FileOutputStream out = new FileOutputStream(imgdist);
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
            JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(tag);
            jep.setQuality(1f, true);
            encoder.encode(tag, jep);
            encoder.encode(tag);
            out.close();


        } catch (IOException ex)
        {
            ex.printStackTrace();
        }
    }


    /**
     * 获得图片宽度，高度
     *
     * @param imgsrc
     * @return result[0]  宽度， result[1] 高度
     */
    public static int[] getImgSize(String imgsrc)
    {

        int result[] = new int[2];

        try
        {

            File fileOne = new File(imgsrc);

            BufferedImage img = ImageIO.read(fileOne);

            result[0] = img.getWidth();

            result[1] = img.getHeight();

        } catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
            log.error(e.getMessage());

        }


        return result;
    }


    private static BufferedImage makeThumbnail(BufferedImage img, int width, int height)
    {
        BufferedImage tag = new BufferedImage(width, height, 1);
        Graphics2D g = tag.createGraphics();
        g.drawImage(img, 0, 0, width, height, null);
        g.dispose();
//		Graphics g = tag.getGraphics();
        tag.getGraphics().drawImage(img.getScaledInstance(width, height, 4), 0, 0, null);
//		g.dispose();
        return tag;
    }

    private static void saveSubImage(BufferedImage image,
                                     Rectangle subImageBounds, File subImageFile) throws IOException
    {
        String fileName = subImageFile.getName();
        String formatName = fileName.substring(fileName.lastIndexOf('.') + 1);
        BufferedImage subImage = new BufferedImage(subImageBounds.width,
                subImageBounds.height, 1);
        Graphics g = subImage.getGraphics();
        if ((subImageBounds.width > image.getWidth())
                || (subImageBounds.height > image.getHeight()))
        {
            int left = subImageBounds.x;
            int top = subImageBounds.y;
            if (image.getWidth() < subImageBounds.width)
                left = (subImageBounds.width - image.getWidth()) / 2;
            if (image.getHeight() < subImageBounds.height)
                top = (subImageBounds.height - image.getHeight()) / 2;
            g.setColor(Color.white);
            g.fillRect(0, 0, subImageBounds.width, subImageBounds.height);
            g.drawImage(image, left, top, null);
            ImageIO.write(image, formatName, subImageFile);
            //System.out.println("if is running left:" + left + " top: " + top);
        } else
        {
            g.drawImage(image.getSubimage(subImageBounds.x, subImageBounds.y,
                    subImageBounds.width, subImageBounds.height), 0, 0, null);
            //System.out.println("else is running");
        }
        g.dispose();
        ImageIO.write(subImage, formatName, subImageFile);
    }

    public static void cut(String srcImageFile, String descDir, int width,
                           int height, Rectangle rect) throws IOException
    {
        BufferedImage image = ImageIO.read(new File(srcImageFile));
        BufferedImage bImage = makeThumbnail(image, width, height);

        saveSubImage(bImage, rect, new File(descDir));
    }

    public static void cut(File srcImageFile, File descDir, int width,
                           int height, Rectangle rect) throws IOException
    {
        BufferedImage image = ImageIO.read(srcImageFile);
        BufferedImage bImage = makeThumbnail(image, width, height);

        saveSubImage(bImage, rect, descDir);
    }


}
